home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Oh!X 2000 Spring
/
Oh!X 2000 Spring Special CD-ROM (Japan) (Part 1).7z
/
Oh!X 2000 Spring Special CD-ROM (Japan) (Part 1).bin
/
MIPSSIM
/
asm16.c
< prev
next >
Wrap
C/C++ Source or Header
|
1999-12-02
|
25KB
|
1,118 lines
#include <stdio.h>
#include "define.h"
void asmips16(char *base, FILE *fp);
#define MAXNAME 31
#define MAXLABEL 10000
static ulong PC;
static int linenum;
static int extended;
#define LittleEndian 0
#define BigEndian 1
static int endian = LittleEndian;
static struct {
char name[MAXNAME+1];
ulong addr;
} label_table[MAXLABEL];
static int labelp = -1;
#define B 0
#define BX 1
#define BC 2
#define BCX 3
#define JMP 4
#define LA 5
static struct {
char name[MAXNAME+1];
ulong idx;
int typ;
} unsolved[MAXLABEL];
int unsolvedp = -1;
#define MAXLOCALF 16
static ulong local_label[256];
static int for_llabel[256][MAXLOCALF];
static int typ_llabel[256][MAXLOCALF];
static int for_index[256];
static int search_label(char *);
static int regist_label(char *, ulong);
static void regist_unsolv(char *,int);
typedef struct {
char *nm;
void (*type)(int);
uint code;
} TABLE;
static void ADDI_TYPE(int);
static void B_TYPE(int);
static void J_TYPE(int);
static void R_TYPE(int);
static void S_TYPE(int);
static void LS_TYPE(int);
static void I_TYPE(int);
#define _CODE(OP,FN) (uint)((OP<<11)|FN)
static TABLE nmtab[]={
"addiu", ADDI_TYPE, _CODE(000,000),
"daddiu", ADDI_TYPE, _CODE(000,001),
"b", B_TYPE, _CODE(002,000),
"jal", J_TYPE, _CODE(003,000),
"jalx", J_TYPE, _CODE(003,001),
"beqz", B_TYPE, _CODE(004,000),
"bnez", B_TYPE, _CODE(005,000),
"sll", S_TYPE, _CODE(006,000),
"dsll", S_TYPE, _CODE(006,001),
"srl", S_TYPE, _CODE(006,002),
"sra", S_TYPE, _CODE(006,003),
"ld", LS_TYPE, _CODE(007,000),
"slti", I_TYPE, _CODE(012,000),
"sltiu", I_TYPE, _CODE(013,000),
"bteqz", B_TYPE, _CODE(014,000),
"btnez", B_TYPE, _CODE(014,001),
"move", I_TYPE, _CODE(014,000),
"li", I_TYPE, _CODE(015,000),
"cmpi", I_TYPE, _CODE(016,000),
"sd", LS_TYPE, _CODE(017,000),
"lb", LS_TYPE, _CODE(020,000),
"lh", LS_TYPE, _CODE(021,000),
"lw", LS_TYPE, _CODE(023,000),
"lbu", LS_TYPE, _CODE(024,000),
"lhu", LS_TYPE, _CODE(025,000),
"lwu", LS_TYPE, _CODE(027,000),
"sb", LS_TYPE, _CODE(030,000),
"sh", LS_TYPE, _CODE(031,000),
"sw", LS_TYPE, _CODE(033,000),
"daddu", R_TYPE, _CODE(034,000),
"addu", R_TYPE, _CODE(034,001),
"dsubu", R_TYPE, _CODE(034,002),
"subu", R_TYPE, _CODE(034,003),
"jalr", R_TYPE, _CODE(035,000),
"jr", R_TYPE, _CODE(035,000),
"slt", R_TYPE, _CODE(035,002),
"sltu", R_TYPE, _CODE(035,003),
"sllv", R_TYPE, _CODE(035,004),
"break", R_TYPE, _CODE(035,005),
"srlv", R_TYPE, _CODE(035,006),
"srav", R_TYPE, _CODE(035,007),
"dsrl", S_TYPE, _CODE(035,010),
"cmp", R_TYPE, _CODE(035,012),
"neg", R_TYPE, _CODE(035,013),
"and", R_TYPE, _CODE(035,014),
"or", R_TYPE, _CODE(035,015),
"xor", R_TYPE, _CODE(035,016),
"not", R_TYPE, _CODE(035,017),
"mfhi", R_TYPE, _CODE(035,020),
"mflo", R_TYPE, _CODE(035,022),
"dsra", S_TYPE, _CODE(035,023),
"dsllv", R_TYPE, _CODE(035,024),
"dsrlv", R_TYPE, _CODE(035,026),
"dsrav", R_TYPE, _CODE(035,027),
"mult", R_TYPE, _CODE(035,030),
"multu", R_TYPE, _CODE(035,031),
"div", R_TYPE, _CODE(035,032),
"divu", R_TYPE, _CODE(035,033),
"dmult", R_TYPE, _CODE(035,034),
"dmultu", R_TYPE, _CODE(035,035),
"ddiv", R_TYPE, _CODE(035,036),
"ddivu", R_TYPE, _CODE(035,037),
/*END*/
};
#define MAXTAB (sizeof(nmtab)/sizeof(TABLE))
#define MAXBUFF 1024
static char Line[MAXBUFF];
static char tmpBuf[MAXBUFF];
static char *linep;
static ulong get_half(ulong addr)
{
ulong word;
word = get_word(addr);
if(addr&3)
return (word>>16)&0xffff;
else
return word&0xffff;
}
static void put_half(ulong addr, ulong code)
{
ulong word;
word = get_word(addr);
if(addr&3)
word = (code<<16)|(word&0xffff);
else
word = (word&0xffff0000)|(code&0xffff);
put_word(addr,word);
}
int regnum( char *reg)
{
int r;
r= 0;
if(strcmp(reg,"r0")==0) r=0;
if(strcmp(reg,"r1")==0) r=1;
if(strcmp(reg,"r2")==0) r=2;
if(strcmp(reg,"r3")==0) r=3;
if(strcmp(reg,"r4")==0) r=4;
if(strcmp(reg,"r5")==0) r=5;
if(strcmp(reg,"r6")==0) r=6;
if(strcmp(reg,"r7")==0) r=7;
if(strcmp(reg,"r8")==0) r=8;
if(strcmp(reg,"r9")==0) r=9;
if(strcmp(reg,"r10")==0) r=10;
if(strcmp(reg,"r11")==0) r=11;
if(strcmp(reg,"r12")==0) r=12;
if(strcmp(reg,"r13")==0) r=13;
if(strcmp(reg,"r14")==0) r=14;
if(strcmp(reg,"r15")==0) r=15;
if(strcmp(reg,"r16")==0) r=16;
if(strcmp(reg,"r17")==0) r=17;
if(strcmp(reg,"r18")==0) r=18;
if(strcmp(reg,"r19")==0) r=19;
if(strcmp(reg,"r20")==0) r=20;
if(strcmp(reg,"r21")==0) r=21;
if(strcmp(reg,"r22")==0) r=22;
if(strcmp(reg,"r23")==0) r=23;
if(strcmp(reg,"r24")==0) r=24;
if(strcmp(reg,"r25")==0) r=25;
if(strcmp(reg,"r26")==0) r=26;
if(strcmp(reg,"r27")==0) r=27;
if(strcmp(reg,"r28")==0) r=28;
if(strcmp(reg,"r29")==0) r=29;
if(strcmp(reg,"r30")==0) r=30;
if(strcmp(reg,"r31")==0) r=31;
if(strcmp(reg,"zero")==0)r=0;
if(strcmp(reg,"at")==0) r=1;
if(strcmp(reg,"v0")==0) r=2;
if(strcmp(reg,"v1")==0) r=3;
if(strcmp(reg,"a0")==0) r=4;
if(strcmp(reg,"a1")==0) r=5;
if(strcmp(reg,"a2")==0) r=6;
if(strcmp(reg,"a3")==0) r=7;
if(strcmp(reg,"t0")==0) r=8;
if(strcmp(reg,"t1")==0) r=9;
if(strcmp(reg,"t2")==0) r=10;
if(strcmp(reg,"t3")==0) r=11;
if(strcmp(reg,"t4")==0) r=12;
if(strcmp(reg,"t5")==0) r=13;
if(strcmp(reg,"t6")==0) r=14;
if(strcmp(reg,"t7")==0) r=15;
if(strcmp(reg,"s0")==0) r=16;
if(strcmp(reg,"s1")==0) r=17;
if(strcmp(reg,"s2")==0) r=18;
if(strcmp(reg,"s3")==0) r=19;
if(strcmp(reg,"s4")==0) r=20;
if(strcmp(reg,"s5")==0) r=21;
if(strcmp(reg,"s6")==0) r=22;
if(strcmp(reg,"s7")==0) r=23;
if(strcmp(reg,"t8")==0) r=24;
if(strcmp(reg,"t9")==0) r=25;
if(strcmp(reg,"k0")==0) r=26;
if(strcmp(reg,"k1")==0) r=27;
if(strcmp(reg,"gp")==0) r=28;
if(strcmp(reg,"sp")==0) r=29;
if(strcmp(reg,"s8")==0) r=30;
if(strcmp(reg,"fp")==0) r=30;
if(strcmp(reg,"ra")==0) r=31;
if(strcmp(reg,"pc")==0) r=0x1000;
return r;
}
static int search_label(char *nam)
{
int i;
for(i=0;i<=labelp;i++)
if(strcmp(label_table[i].name,nam)==0)
break;
if(i>labelp) return -1;/* not found */
return i;/* found */
}
static int regist_label(char *nam, ulong pc)
{
if(search_label(nam)>=0)
return -1;/* duplicated definition */
if((labelp+1)>=MAXLABEL)
return -2;/* table overflow */
++labelp;
strncpy(label_table[labelp].name,nam,MAXNAME);
label_table[labelp].addr = pc;
return 0;
}
static void regist_unsolv(char *nam, int typ)
{
if((unsolvedp+1)>=MAXLABEL){
fprintf(stderr,"%d: too many unsolved labels!\n",linenum);
return;
}
unsolvedp++;
strncpy(unsolved[unsolvedp].name,nam,MAXNAME);
unsolved[unsolvedp].idx = PC;
unsolved[unsolvedp].typ = typ;
}
static void add_label(ulong dst, int idx, int typ)
{
ulong org;
ulong code;
long imm;
switch(typ){
case B:
org = idx;
code = get_half(idx);
code |= (((dst-(org+2))>>1)&0x7ff);
put_half(idx,code);
break;
case BC:
org = idx;
code = get_half(idx);
code |= (((dst-(org+2))>>1)&0xff);
put_half(idx,code);
break;
case BCX:
org = idx;
imm = (dst-(org+4))>>1;
code = (0xf000|(imm&0x7e0)|((imm>>11)&0x1f));
put_half(idx,code);
code = get_half(idx+2);
code|= (imm&0x1f);
put_half(idx+2,code);
break;
case JMP:
imm = (dst>>2)&0x3ffffff;
code = imm & 0xffff;
put_half(idx+2,code);
code = get_half(idx);
code |= (((imm>>11)&0x3e0)|((imm>>21)&0x1f));
put_half(idx,code);
break;
case LA:
code = get_half(idx+4);
code |= ((dst )&0xffff);
put_half(idx+4,code);
code = get_half(idx+6);
code |= ((dst>>16)&0xffff);
put_half(idx+6,code);
break;
}
}
static void solve_label(void)
{
int i;
int l;
for(i=0;i<=unsolvedp;i++){
if((l=search_label(unsolved[i].name))<0){
fprintf(stderr,"unsolved label: %s\n",unsolved[i].name);
}
else{
add_label(label_table[l].addr,unsolved[i].idx,unsolved[i].typ);
}
}
}
static void solve_local(int n)
{
int i;
for(i=0;i<=for_index[n];i++){
add_label(local_label[n],for_llabel[n][i],typ_llabel[n][i]);
}
for_index[n] = -1;
}
static void put_code(ulong addr, ulong code)
{
if(extended==0){
put_half(addr,code);
}
else{
put_half(addr,code>>16);
put_half(addr+2,code);
}
}
static int white(int ch)
{
return (ch==' ')||(ch=='\t');
}
static int eol(int ch)
{
return (ch=='\n')||(ch=='\0')||(ch=='\r');
}
static int delim(int ch)
{
return (ch==',')||white(ch)||(ch=='(')||(ch==')')||(ch==':');
}
static void scan_sym(char *to)
{
while(delim(*linep)) linep++;
while((!eol(*linep)) && (!delim(*linep))) *to++ = *linep++;
if(*linep==':'){
*to++ = ':';
linep++;
}
*to='\0';
}
static int chk_num(int ch, int rad)
{
ch &= 0xff;
if(rad<=10){
ch=ch-'0';
if((ch>=0)&&(ch<rad)) return ch;
else return -1;
}
if(rad==16){
if((ch>='0')&&(ch<='9')) return ch-'0';
if((ch>='a')&&(ch<='f')) return ch-'a'+10;
if((ch>='A')&&(ch<='F')) return ch-'A'+10;
return -1;
}
return -1;
}
static char last_ch;
static ulong label_value;
#define LABEL 0
#define LOCALF 1
#define LOCALB 2
#define ADDR 3
static int check_label(char *sym)
{
if((*sym<'0')||(*sym>'9'))
return LABEL;
label_value = (ulong)gen_val(sym);
if(last_ch=='f')
return LOCALF;
if(last_ch=='b')
return LOCALB;
return ADDR;
}
static int islocal(char *sym)
{
int v=0;
while(*sym){
if((*sym<'0')||(*sym>'9'))
break;
v = v*10+(*sym-'0');
sym++;
}
if(*sym=='\0')
return v;
return 0;
}
static void R_TYPE(int insn)
{
int fn;
int rx,ry,rz;
if(((fn=nmtab[insn].code)&(_CODE(037,000)))==(_CODE(034,000))){/* RRR */
scan_sym(tmpBuf);
rz = regnum(tmpBuf)&0x7;
scan_sym(tmpBuf);
rx = regnum(tmpBuf)&0x7;
scan_sym(tmpBuf);
ry = regnum(tmpBuf)&0x7;
}
else{ /* RR */
rz = 0;
if((fn&037)==0){/* J(AL)R */
scan_sym(tmpBuf);
rx = regnum(tmpBuf)&0x1f;
if(rx==31){ /* JR RA */
rx = 0;
ry = 1;
}
else{
rx &= 7;
if(strcmp(nmtab[insn].nm,"jr")==0)
ry = 0;
else
ry = 2;
}
}
else if(((fn&037)==020)||((fn&037)==022)){/* MFLO/MFHI */
scan_sym(tmpBuf);
rx = regnum(tmpBuf)&7;
ry = 0;
rz = 0;
}
else if(fn==_CODE(035,005)){/* BREAK */
scan_sym(tmpBuf);
rz = (int)gen_val(tmpBuf);
rx = (rz>>3)&7;
ry = rz&7;
rz = 0;
}
else{
scan_sym(tmpBuf);
rx = regnum(tmpBuf)&7;
scan_sym(tmpBuf);
ry = regnum(tmpBuf)&7;
rz = 0;
switch(fn&037){
case 004:/* SLLV */
case 006:/* SRLV */
case 007:/* SRAV */
case 024:/* DSLLV */
case 026:/* DSRLV */
case 027:/* DSRAV */
rz = rx;
rx = ry;
ry = rz;
rz = 0;
}
}
}
fn |= ((rx<<8)|(ry<<5)|(rz<<2));
extended = 0;
put_code(PC,fn);
}
static void I_TYPE(int insn)
{
int fn;
int rx,ry,rz;
long imm;
int ex;
if(((fn=nmtab[insn].code)&(_CODE(017,0)))==(_CODE(014,0))){/* MOVE */
extended = 0;
ex = 0;
scan_sym(tmpBuf);
imm = regnum(tmpBuf);
scan_sym(tmpBuf);
ry = regnum(tmpBuf);
if((imm>7)||(imm==0)||(imm==1)){ /* MOV32R */
rx = 5;
rz = ry;
ry = imm & 7;
imm = (imm&0x18)|(rz&7);
rz = 0;
}
else{ /* MOVR32 */
rx = imm;
imm = ry;
ry = rx;
rx = 7;
ry &= 7;
rz = 0;
imm &= 0x1f;
}
}
else{
scan_sym(tmpBuf);
rx = regnum(tmpBuf)&7;
ry = 0;
rz = 0;
scan_sym(tmpBuf);
imm = gen_val(tmpBuf);
if(extended||(imm&0xffffff00)){
extended = 1;
ex = 0xf000|(imm&0x7e0)|((imm>>11)&0x1f);
imm &= 0x1f;
}
else{
extended = 0;
ex = 0;
}
}
fn |= ((rx<<8)|(ry<<5)|(rz<<2)|imm);
put_code(PC,(ulong)((ex<<16)|fn));
}
static void B_TYPE(int insn)
{
int fn;
int rx;
long imm,imm2;
long mask;
int ex;
int cl;
switch(fn=nmtab[insn].code){
case _CODE(004,000):/* BEQZ */
case _CODE(005,000):/* BNEZ */
scan_sym(tmpBuf);
rx=regnum(tmpBuf);
mask=0xff;
break;
case _CODE(002,000):/* B */
rx=0;
mask=0x7ff;
break;
default:
rx=fn&1;
fn &= 0xff00;
mask=0xff;
}
scan_sym(tmpBuf);
if((cl=check_label(tmpBuf))==ADDR){
imm = (long)((label_value-(PC+2)))>>1;
if(imm<0)
imm = -imm;
if((imm>mask)||extended){
extended=1;
imm = (label_value-(PC+4))>>1;
ex = 0xf000|(imm&0x7e0)|((imm>>11)&0x1f);
imm &= 0x1f;
}
else{
imm = (label_value-(PC+2))>>1;
imm &= mask;
ex = 0;
}
}
else if(cl==LOCALB){
imm2 = (long)local_label[label_value&0xff];
imm = (long)((imm2-(PC+2)))>>1;
if(imm<0)
imm = -imm;
if((imm>mask)||extended){
extended=1;
imm = (imm2-(PC+4))>>1;
ex = 0xf000|(imm&0x7e0)|((imm>>11)&0x1f);
imm &= 0x1f;
}
else{
imm = (imm2-(PC+2))>>1;
imm &= mask;
ex = 0;
}
}
else if(cl==LOCALF){
cl = (for_index[label_value&0xff]+1) % MAXLOCALF;
for_llabel[label_value&0xff][cl]=PC;
typ_llabel[label_value&0xff][cl]=(extended)? BCX:
((mask==0xff)? BC:B);
for_index[label_value&0xff]=cl;
imm = 0;
ex = 0;
}
else {
int i;
i = search_label(tmpBuf);
if(i<0){
regist_unsolv(tmpBuf,(extended)? BCX:BC);
imm = 0;
ex = 0;
}
else {
imm2 = (long)label_table[i].addr;
imm = (long)((imm2-(PC+2)))>>1;
if(imm<0)
imm = -imm;
if((imm>mask)||extended){
extended=1;
imm = (imm2-(PC+4))>>1;
ex = 0xf000|(imm&0x7e0)|((imm>>11)&0x1f);
imm &= 0x1f;
}
else{
imm = (imm2-(PC+2))>>1;
imm &= mask;
ex = 0;
}
}
}
put_code(PC,(ulong)((ex<<16)|(fn)|(rx<<8)|imm));
}
static void J_TYPE(int insn)
{
ulong targ;
ulong code;
int rx,fn;
int cl;
extended = 1;
scan_sym(tmpBuf);
if((cl=check_label(tmpBuf))==ADDR){
targ = gen_val(tmpBuf);
targ =(targ>>2)&0x3ffffff;
}
else if(cl==LOCALB){
targ = local_label[label_value&0xff];
targ =(targ>>2)&0x3ffffff;
}
else if(cl==LOCALF){
cl = (for_index[label_value&0xff]+1) % MAXLOCALF;
for_llabel[label_value&0xff][cl]=PC;
typ_llabel[label_value&0xff][cl]=JMP;
for_index[label_value&0xff]=cl;
targ = 0;
}
else {
int i;
i = search_label(tmpBuf);
if(i<0){
regist_unsolv(tmpBuf,JMP);
targ = 0;
}
else {
targ = label_table[i].addr;
targ=(targ>>2)&0x3ffffff;
}
}
fn = nmtab[insn].code;
rx = fn&1;
code =(fn&0xfffe)|
((targ&0xffff)<<16)|
((targ>>11)&0x3e0)|
((targ>>21)&0x1f)|
(rx<<10);
code = (code<<16)|((code>>16)&0xffff);
put_code(PC,code);
}
static void ADDI_TYPE(int insn)
{
int d;
int ex,c;
int rx,ry;
long imm,imm2;
if((nmtab[insn].code)==_CODE(0,0))
d=0x00;/* ADDIU */
else
d=0x10;/* DADDIU */
scan_sym(tmpBuf);
rx=regnum(tmpBuf);
scan_sym(tmpBuf);
ry=regnum(tmpBuf);
if(ry==0){ /* ADDIU rx,imm */
imm = gen_val(tmpBuf);
imm2 = (imm<0)? -imm: imm;
if(rx==29){/* SP */
rx=0;
if(d)
c = 0xfb00;
else
c = 0x6300;
imm2 &= 0xffffff80;
if(imm2||extended){
extended = 1;
ex = 0xf000|(imm&0x7e0)|((imm>>11)&0x1f);
imm &= 0x1f;
}
else
imm = (imm>>3)&0xff;
}
else{
if(d){
ry=rx;
rx=0;
c = 0xfd00;
imm2 &= 0xfffffff0;
}
else{
c = 0x4800;
imm2 &= 0xffffff80;
}
if(imm2||extended){
extended = 1;
ex = 0xf000|(imm&0x7e0)|((imm>>11)&0x1f);
imm &= 0x1f;
}
else{
if(d)
imm = imm&0x1f;
else
imm = imm&0xff;
}
}
}
else{ /* ADDIU ry,rx,imm */
scan_sym(tmpBuf);
imm = gen_val(tmpBuf);
imm2 = (imm<0)? -imm: imm;
if(ry==0x1000){/* PC */
if(d){
ry = rx;
rx = 0;
c = 0xfe00;
}
else{
ry = 0;
c = 0x0800;
}
imm >>= 2;
imm2 >>= 2;
imm2 &= 0xffffff80;
if((imm<0)||imm2||extended){
extended = 1;
imm <<= 2;
ex = 0xf000|(imm&0x7e0)|((imm>>11)&0x1f);
imm &= 0x1f;
}
else{
ex = 0;
imm &= 0xff;
}
}
else if(ry==29){/* SP */
if(d){
ry=rx;
rx=0;
c = 0xff00;
}
else{
ry = 0;
c = 0x0000;
}
imm >>= 2;
imm2 >>= 2;
imm2 &= 0xffffff80;
if((imm<0)||imm2||extended){
extended = 1;
imm <<= 2;
ex = 0xf000|(imm&0x7e0)|((imm>>11)&0x1f);
imm &= 0x1f;
}
else{
ex = 0;
imm &= 0xff;
}
}
else{
c = ry;
ry = rx;
rx = c;
c = 0x4000+d;
imm2 &= 0xfffffff8;
if(imm2||extended){
extended = 1;
ex = 0xf000|(imm&0x7f0)|((imm>>11)&0xf);
imm &= 0xf;
}
else{
ex = 0;
imm &= 0xf;
}
}
}
put_code(PC,(ulong)((ex<<16)|c|(rx<<8)|(ry<<5)|imm));
}
static void LS_TYPE(int insn)
{
int rx,ry;
long offset,offset2;
int fn;
int sa;
int ex;
scan_sym(tmpBuf);
ry=regnum(tmpBuf);
scan_sym(tmpBuf);
offset=gen_val(tmpBuf);
scan_sym(tmpBuf);
rx=regnum(tmpBuf);
switch(fn=nmtab[insn].code){
case _CODE(021,000):/* LH */
case _CODE(025,000):/* LHU */
case _CODE(031,000):/* SH */
sa=1;
break;
case _CODE(023,000):/* LW/SW */
case _CODE(033,000):/* LW/SW */
case _CODE(027,000):/* LWU */
sa=2;
break;
case _CODE(007,000):/* LD */
case _CODE(017,000):/* SD */
sa=3;
break;
default:/* LB/LBU/SB */
sa=0;
}
offset2=offset>>sa;
if((offset<0)||(offset2&0xffffffe0)||extended){
extended=1;
ex=0xf000|(offset&0x7e0)|((offset>>11)&0x1f);
offset &= 0x1f;
}
else{
ex=0;
offset=offset2&0x1f;
}
if((sa==2)||(sa==3)){
switch(fn){
case _CODE(023,000):/* LW */
if(rx==29){ /* SP */
rx=ry;
ry=0;
fn=0x9000;
}
else if(rx==0x1000){/* PC */
rx=ry;
ry=0;
fn=0xb000;
}
break;
case _CODE(007,000):/* LD */
if(rx==29){ /* SP */
rx=0;
fn=0xf800;
}
else if(rx==0x1000){/* PC */
rx=4;
fn=0xf800;
}
break;
case _CODE(033,000):/* SW */
if(rx==29){/* SP */
if(ry==31){/* RA */
rx=2;
ry=0;
fn=0x6000;
}
else{
rx=ry;
ry=0;
fn=0xd000;
}
}
break;
case _CODE(017,000):/* SD */
if(rx==29){/* SP */
if(ry==31){/* RA */
rx=2;
ry=0;
fn=0xf800;
}
else{
rx=1;
fn=0xf800;
}
}
break;
}
}
rx &= 7;
ry &= 7;
put_code(PC,(ulong)((ex<<16)|fn|(rx<<8)|(ry<<5)|offset));
}
static void S_TYPE(int insn)
{
int rx,ry;
int fn;
int ex;
long sa;
switch(fn=nmtab[insn].code){
case _CODE(035,010):/* DSRL */
case _CODE(035,023):/* DSRA */
scan_sym(tmpBuf);
ry=regnum(tmpBuf)&0x7;
scan_sym(tmpBuf);
sa=gen_val(tmpBuf)&0x3f;
if((sa==0)||(sa>8)||extended){
extended=1;
rx=0;
ex=0xf000|((sa&0x1f)<<6)|(sa&0x20);
}
else{
rx=sa&0x7;
ex=0;
}
sa=0;
break;
default:
scan_sym(tmpBuf);
rx=regnum(tmpBuf)&0x7;
scan_sym(tmpBuf);
ry=regnum(tmpBuf)&0x7;
scan_sym(tmpBuf);
sa=gen_val(tmpBuf)&0x3f;
if((sa==0)||(sa>8)||extended){
extended=1;
ex=0xf000|((sa&0x1f)<<6)|(sa&0x20);
sa=0;
}
else{
ex=0;
sa &= 0x7;
}
}
put_code(PC,(ulong)((ex<<16)|fn|(rx<<8)|(ry<<5)|(sa<<2)));
}
static ulong asmcpu(ulong pc, char *buf)
{
int i;
long tmp;
int reg;
labelp = -1;
unsolvedp = -1;
for(i=0;i<MAXTAB;i++)
if(strcmp(tmpBuf,nmtab[i].nm)==0) break;
if(i>=MAXTAB){
if(strcmp(tmpBuf,"nop")==0){
put_code(PC,0xEA4D);
return PC+2;
}
if(strcmp(tmpBuf,".org")==0){
scan_sym(tmpBuf);
return (ulong)gen_val(tmpBuf);
}
if(strcmp(tmpBuf,".align")==0){
scan_sym(tmpBuf);
tmp = gen_val(tmpBuf);
return PC+(tmp-(PC%tmp));
}
if(strcmp(tmpBuf,".word")==0){
extended = 0;
scan_sym(tmpBuf);
while(tmpBuf[0]!='\0'){
tmp = gen_val(tmpBuf);
if(endian==LittleEndian){
put_code(PC+0,(tmp&0xffff));
put_code(PC+2,((tmp>>16)&0xffff));
}
else{
put_code(PC+0,((tmp>>16)&0xffff));
put_code(PC+2,(tmp&0xffff));
}
PC += 4;
scan_sym(tmpBuf);
}
return PC;
}
if(strcmp(tmpBuf,"la")==0){
int cl;
extended = 0;
if(PC&3){
put_code(PC,0xEA4D);
PC += 2;
}
scan_sym(tmpBuf);
reg = regnum(tmpBuf)&0x7;
scan_sym(tmpBuf);
if((cl=check_label(tmpBuf))==ADDR){
tmp = gen_val(tmpBuf);
}
else if(cl==LOCALB){
tmp = local_label[label_value&0xff];
}
else if(cl==LOCALF){
cl = (for_index[label_value&0xff]+1) % MAXLOCALF;
for_llabel[label_value&0xff][cl]=PC;
typ_llabel[label_value&0xff][cl]=LA;
for_index[label_value&0xff]=cl;
tmp = 0;
}
else {
int i;
i = search_label(tmpBuf);
if(i<0){
regist_unsolv(tmpBuf,LA);
tmp = 0;
}
else {
tmp = label_table[i].addr;
}
}
put_code(PC+0,0xb001|(reg<<8));
put_code(PC+2,0x1002);
if(endian==LittleEndian){
put_code(PC+4,(tmp&0xffff));
put_code(PC+6,((tmp>>16)&0xffff));
}
else{
put_code(PC+4,((tmp>>16)&0xffff));
put_code(PC+6,(tmp&0xffff));
}
return PC+8;
}
if(tmpBuf[0]==0)
return pc;
fprintf(stderr,"%d: unknown nmemonic!\n",linenum);
return pc;
}
(nmtab[i].type)(i);
i = (extended)? 4: 2;
extended = 0;
return pc+i;
}
void asmips16(char *base, FILE *fp)
{
int i;
if(*base!='\0')
PC = gen_val(base);
linenum = 0;
for(i=1;i<256;i++)
for_index[i] = -1;
printf("%08x ",PC);fflush(stdout);
while(fgets(Line,MAXBUFF,fp)!=NULL){
linep = Line;
linenum++;
scan_sym(tmpBuf);
if(tmpBuf[0]=='q')/* quit */
break;
if(tmpBuf[0]=='\0')/* null line */
goto next;
if(tmpBuf[0]=='#') /* comment line */
goto next;
i = strlen(tmpBuf);
if(tmpBuf[i-1]==':'){ /* label */
/* process label */
tmpBuf[i-1]='\0';
if(i=islocal(tmpBuf)){
local_label[i&0xff]=PC;
solve_local(i&0xff);
}
else if(regist_label(tmpBuf,PC)<0)
fprintf(stderr,"%d: label error!\n",linenum);
scan_sym(tmpBuf);
if(tmpBuf[0]=='\0')
goto next;
}
if((i>1)&&(tmpBuf[i-1]=='e')&&(tmpBuf[i-2]=='.')){
extended = 1;
tmpBuf[i-2]='\0';
}
else
extended = 0;
PC = asmcpu(PC,tmpBuf);
next:
printf("%08x ",PC);fflush(stdout);
}
solve_label();
}